package com.crecheng.shop.util;

import java.awt.*;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.nio.CharBuffer;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

public final class CSVUtil {

    public static String splitString=",";

    public static  <T> List<T> parse(Class<T> objClass,String path,boolean flag){
        List<T> list=new ArrayList<>();
        if(flag)
            path+=objClass.getSimpleName()+".csv";
        String s=fileGetAllString(path);
        String[] datas=s.split("\n");
        if(datas.length<1)
            return list;
        String[] colNames=datas[0].split(splitString);
        var fields=Util.getAllFields(objClass);
        Map<String, Field> fieldMap=new HashMap<>();
        for (var f:fields){
            f.setAccessible(true);
            fieldMap.put(f.getName().toLowerCase(),f);
        }

        for (int i = 0; i < colNames.length; i++) {
            colNames[i]=colNames[i].toLowerCase();
        }

        for (int i = 1; i < datas.length; i++) {
            if(datas[i].length()<1)
                continue;
            var data=datas[i].split(splitString);
            T t=null;
            try {
                t=objClass.getDeclaredConstructor().newInstance();
            } catch (InstantiationException | IllegalAccessException |
                    InvocationTargetException | NoSuchMethodException e) {
                e.printStackTrace();
            }
            if(t==null)
                continue;
            for (int i1 = 0; i1 < colNames.length; i1++) {
                if(fieldMap.containsKey(colNames[i1]))
                {
                    var field=fieldMap.get(colNames[i1]);
                    Object d=getObject(field,data[i1]);
                    try {
                        field.set(t,d);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
            list.add(t);
        }
        return list;
    }

    public static  <T> List<T> parse(Class<T> objClass,String path){
        return parse(objClass,path,true);
    }

    static String fileGetAllString(String path){
        if(path==null||path.trim().length()<1)
            return "";
        File file=new File(path);
        if(!file.exists())
            return "";
        BufferedReader fr=null;
        try {
            fr=new BufferedReader(new FileReader(file));
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(fr==null)
            return "";
        StringBuffer sb=new StringBuffer();
        String tmp="" ;
        try {
        while ((tmp=fr.readLine())!=null){
            sb.append(tmp).append("\n");
        }}
        catch (IOException exception){
            exception.printStackTrace();
        }finally {
            try {
                fr.close();
            } catch (IOException exception) {
                exception.printStackTrace();
            }
        }
        return sb.toString();
    }

    static boolean fileWriteAllString(String text,String path) {
        if (path == null || path.trim().length() < 1 || text == null || text.length() < 1)
            return false;

        File file = new File(path);
        FileWriter fileWriter = null;
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            fileWriter = new FileWriter(file);
            fileWriter.write(text);
            return true;
        } catch (Exception exception) {
            exception.printStackTrace();
            return false;
        } finally {
            if (fileWriter != null) {
                try {
                    fileWriter.close();
                } catch (IOException exception) {
                    exception.printStackTrace();
                }
            }
        }
    }



    public static <T> void export(Class<T> objClass,List<T> list,String path){
        StringBuffer str=new StringBuffer();
        if(list.size()<1)
            return;
        var fields=Util.getAllFields(objClass);
        for (int i1 = 0; i1 < fields.size(); i1++) {
            if(i1!=0)
                str.append(splitString);
            fields.get(i1).setAccessible(true);
            str.append(fields.get(i1).getName().toLowerCase());
        }
        str.append("\n");
        try {
        for (var d:list){
            for (int i = 0; i < fields.size(); i++) {
                if(i!=0)
                    str.append(splitString);
                var f=fields.get(i);
                str.append(f.get(d).toString());
            }
            str.append("\n");
        }
        fileWriteAllString(str.toString(),path+objClass.getSimpleName()+".csv");
        }
        catch (Exception ex){
            ex.printStackTrace();
        }
    }

    public static Object getObject(Field f,String s){
        String typeName = f.getType().getName();
        Object con = null;
        switch (typeName) {
            case "int": case "java.lang.Integer":
                con = Integer.parseInt(s);
                break;
            case "java.lang.String":
                con = s;
                break;
            case "float": case "java.lang.Float":
                con = Float.parseFloat(s);
                break;
            case "java.sql.Date":
                SimpleDateFormat sp=new SimpleDateFormat("yyyy-MM-dd");
                try {
                    con = sp.parse(s);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                break;
            case "java.sql.Time":
                SimpleDateFormat sp1=new SimpleDateFormat("HH:mm:ss");
                try {
                    con = sp1.parse(s);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                break;
            case "java.sql.Timestamp":
                SimpleDateFormat sp2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                try {
                    con=new Timestamp(sp2.parse(s).getTime());
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                break;
        }
        return con;
    }
}
